#pragma once

#ifndef _CLIENT_SYSTEM_SERVER_HANDLER_H_
#define _CLIENT_SYSTEM_SERVER_HANDLER_H_

#include "Core\StanzaHandler.h"
#include "Core\Packages.h"

#include "Poco\BasicEvent.h"
#include "Poco\SharedPtr.h"
#include "Poco\Net\SocketAddress.h"

namespace ExamSystem
{
    using Poco::BasicEvent;
    using Poco::SharedPtr;
    using Poco::Net::SocketAddress;

    class CPackage;

namespace Client
{
    class CClientSystem;
    /**************************************************************************\
     Component:     CServerHandler
     Description:
        This class manages the connection to the (root) server. It has a FSM to 
        record the states.
    \**************************************************************************/
    class CServerHandler : public CStanzaHandler
    {
    public:
        CServerHandler(CClientSystem *clientSystem);
        ~CServerHandler(void);

    public:
        // start the FSM
        void StartHandler(void);

    protected:
        // stanza handlers
        virtual void startElement(CXMLConnection *connection, const XMLString& uri, const XMLString& localName, const XMLString& qname, const Attributes& attributes);
        virtual void endElement(CXMLConnection *connection, const XMLString& uri, const XMLString& localName, const XMLString& qname);
        virtual void characters(CXMLConnection *connection, const XMLChar ch[], int start, int length);

    public:
        // events
        BasicEvent<void *const> eventVersionCheckFailed;
        BasicEvent<SocketAddress> eventConnectionRedirected;
        BasicEvent<CLoginResultPackage> eventLoginResult;
        BasicEvent<void *const> eventReady;

    protected:
        // register sensitive package types
        void RegisterPackageTypes(void);

        // process received package
        void ProcessPackage(void);

    protected:
        // package handlers
        void ResultPackageHandler(void);
        void OrderPackageHandler(void);
        void MessagePackageHandler(void);
        void InformationPackageHandler(void);
        void RedirectPackageHandler(void);
        void LoginResultPackageHandler(void);
        void IDAllocPackageHandler(void);
        void QuestionPackageHandler(void);
        void CriterionPackageHandler(void);

    protected:
        // the server system
        CClientSystem *m_clientSystem;

        // current package
        SharedPtr<CPackage> m_currentPackage;

        // here we directly manage the internal connection
        SharedPtr<CXMLConnection> m_xmlConnection;

        enum ConnectionState {
            stateStart,
            stateCheckingSystemVersion,
            stateRedirecting,
            stateReady
        };
        ConnectionState m_presentState;

        typedef void (CServerHandler::*PackageHandler)(void);
        std::map<std::string, PackageHandler> m_packageHandlers;
    };
}
}
#endif